package com.ys.day29.Reflect.p8使用反射调用方法;

import com.ys.day29.Reflect.p6Reflect与Constructor对象.Student;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

/**
 * 描述:
 *
 *
 * @author CodeYang
 * @version 2021/1/11 23:11
 */
public class P1使用反射调用方法 {

    public static void main(String[] args) {

        function01();
        function02();
    }

    /**
     * 使用反射调用有参方法
     *  * 场景：使用反射调用有参方法setStuName(String)
     *  * 步骤：
     *  * 1反射入口
     *  * 2获取构造器签名
     *  * 3调用newInstance()方法创建对象
     *  * 4设置参数类型和参数实际的值
     *  * 5调用invoke()方法完成方法调用
     *  *
     */
    private static void function02() {
        // 反射入口
        Class<Student> aClass = Student.class;

        try {
            // 获取构造器签名
            Constructor<Student> constructor = aClass.getDeclaredConstructor();
            // 使用构造器创建对象
            Student student = constructor.newInstance();
            System.out.println("调用setName之前的对象:"+student);
            // 定义参数列表
            Class<?>[] params = {String.class};
            // 定义参数列表值
            Object[] values = {"diy"};
            //根据方法名创建 方法签名
            Method setName = aClass.getDeclaredMethod("setName", params);
            // 通过反射调用 method
            Object invoke = setName.invoke(student, values);
            // this setName return is void so return null
            System.out.println(invoke);

            System.out.println("调用setName方法之后的对象"+student);

        }catch (Exception e){
            e.printStackTrace();
        }
    }

    /**
     *  使用反射调用有参方法
     *   * 场景：使用反射调用Student对象的getStuName()方法
     *  * 步骤：
     *  * 1反射入口
     *  * 2获取Constructor对象
     *  * 3调用newInstrance()方法创建无参对象
     *  * 4根据方法名称获取成员方法签名
     *  * 5调用Method对象的invoke()方法完成方法调用
     */
    private static void function01() {
        Student student = new Student();
        student.setName("ABCD");
        System.out.println("before:"+student);

        // 反射入口
        try {
            Class<Student> studentClass = Student.class;
            // 获得无参构造方法
            Constructor<Student> constructor = studentClass.getDeclaredConstructor();
            //使用 无参构造方法签名 创建对象
            Student student1 = constructor.newInstance();
            System.out.println("after:"+student1);

            // 获得方法签名
            Method getName = studentClass.getDeclaredMethod("getName");
            /**
             * invoke(Object obj,Object...params) 方法是Method的成员方法,用于通过反射调用方法
             * 参数1: 调用对象
             * 参数2: 参数列表
             * return 正常调用的返回类型
             */
            Object invoke = getName.invoke(student1);
            // 这里调用的是 新的 对象所以返回的null
            System.out.println(invoke);


        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}
